package com.xrui.hbase.codec.impl;

import com.google.common.base.Preconditions;
import com.moz.kiji.delegation.Lookups;
import com.xrui.hbase.DecodedCell;
import com.xrui.hbase.codec.CellEncoder;
import com.xrui.hbase.schema.SchemaType;
import com.xrui.hbase.schema.impl.CustomCellSchema;
import com.xrui.hbase.schema.spec.CellSpec;


import java.io.IOException;

/**
 * Serializes Custom object for persistence into an HBase cell.
 * <p>
 * <p>
 * A Custom cell encoder is specific to one column in a DatabaseTable.
 * Custom encoder and decoder classes know how to encode and decode themselves.
 * <p>
 */
public final class CustomCellEncoder implements CellEncoder {
    /**
     * Specification of the column encoding.
     */
    private final CellSpec mCellSpec;
    /**
     * Encoder of the custom object to encode.
     */
    private final CellEncoder mCellEncoder;

    /**
     * Creates a new <code>CellEncoder</code> instance.
     *
     * @param cellSpec Specification of the cell to encode.
     * @throws IOException on I/O error.
     */
    public CustomCellEncoder(final CellSpec cellSpec) throws IOException {
        mCellSpec = Preconditions.checkNotNull(cellSpec);
        Preconditions.checkArgument(cellSpec.getCellSchema().getType() == SchemaType.CUSTOM);
        CustomCellSchema cellSchema = (CustomCellSchema) cellSpec.getCellSchema();
        mCellEncoder = Lookups.getNamed(CellEncoder.class).lookup();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public byte[] encode(final DecodedCell<?> cell) throws IOException {
        return encode(cell.getData());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized <T> byte[] encode(final T cellValue) throws IOException {
        return mCellEncoder.encode(cellValue);
    }

    @Override
    public String getName() {
        return this.getClass().getName();
    }
}
